/*
 * Copyright Iain Sproat, 2009
 * 
 *
 */

using System;
using System.Collections.Generic;
using FreeBase;
using FreeBase.Domain;
using Newtonsoft.Json;
using NUnit.Framework;

namespace FreeBase_Test
{
	[TestFixture]
	public class TestResponseParser
	{
		[Test]
		public void TestParseArtist()
		{
			
			string responseToParse = "{" +
				"\"status\":\"200 OK\"," +
				"\"code\":\"/api/status/ok\"," +
				"\"result\":[{" +
				"\"id\":\"/en/the_police\"," +
				"\"name\":\"The Police\"" +
				"}]," +
				"\"transaction_id\":\"cache:cache01.p01.sjc1:8101...\"" +
				"}";
			
			IResponseParser rp = new ResponseParser();
			Response<Artist> r = rp.Parse<Artist>( responseToParse );
			Assert.IsNotNull( r );
			Assert.AreEqual( "200 OK", r.Status );
			Assert.AreEqual( "/api/status/ok", r.Code );
			Assert.AreEqual( "cache:cache01.p01.sjc1:8101...", r.TransactionId );
			Assert.AreEqual( "The Police", r.Result[0].Name.Value );
			Assert.AreEqual( "/en/the_police", r.Result[0].Id.Value );
		}
		
		[Test]
		public void TestParseTrackName()
		{
			string responseToParse = "{" +
				"\"status\":\"200 OK\"," +
				"\"code\":\"/api/status/ok\"," +
				"\"result\":[{" +
				"\"track\":[{" +
				"\"name\":\"Message In a Bottle\"" +
				"}]" +
				"}]," +
				"\"transaction_id\":\"cache:cache01.p01.sjc1:8101...\"" +
				"}";
			IResponseParser rp = new ResponseParser();
			Response<Artist> r = rp.Parse<Artist>( responseToParse );
			Assert.IsNotNull( r );
			Assert.AreEqual( "200 OK", r.Status );
			Assert.AreEqual( "/api/status/ok", r.Code );
			Assert.AreEqual( "cache:cache01.p01.sjc1:8101...", r.TransactionId );
			Assert.AreEqual( "Message In a Bottle", r.Result[0].Track[0].Name.Value );
		}
		
		#region Testing My Understanding of the Newtonsoft.Json Deserializer
		[Test]
		public void DeserializeSimpleObject()
		{
			SimpleObject so = JsonConvert.DeserializeObject<SimpleObject>( "{\"Property1\":\"hello\",\"Property2\":\"world\"}" );
			Assert.AreEqual( "hello", so.Property1 );
			Assert.AreEqual( "world", so.Property2 );
		}
		
		
		
		[Test]
		public void DeserializeNestedObject()
		{
			NestedObject no = JsonConvert.DeserializeObject<NestedObject>("{\"PropertyA\":\"hello world\",\"nested\":{\"Property1\":\"hello\",\"Property2\":\"world\"}}");
			Assert.IsNotNull( no );
			Assert.AreEqual( "hello world", no.PropertyA );
			Assert.IsNotNull( no.nested );
			Assert.AreEqual( "hello", no.nested.Property1 );
			Assert.AreEqual( "world", no.nested.Property2 );
		}
		
		
		
		[Test]
		public void DeserializeImplicit()
		{
			ImpliedObject io = JsonConvert.DeserializeObject<ImpliedObject>("{\"Property1\":\"hello\",\"Property2\":\"world\"}");
			Assert.IsNotNull( io );
			Assert.AreEqual( new Implied( "hello" ).Value, io.Property1.Value );
			Assert.AreEqual( "world", io.Property2 );
			
			io = JsonConvert.DeserializeObject<ImpliedObject>("{\"Property1\":{\"Value\":\"hello\"},\"Property2\":\"world\"}");
			Assert.IsNotNull( io );
			Assert.AreEqual( "hello", io.Property1.Value );
			Assert.AreEqual( "world", io.Property2 );
			
			ImpliedObject2 io2 = JsonConvert.DeserializeObject<ImpliedObject2>("{\"Property1\":{\"value\":\"hello\"},\"Property2\":\"world\"}");
			Assert.IsNotNull( io );
			Assert.AreEqual( "hello", io2.Property1.Value );
			Assert.AreEqual( "world", io2.Property2 );
		}
		
		[Test]
		public void DeserializeInternalArray()
		{
			ArrayObject ao = JsonConvert.DeserializeObject<ArrayObject>("{\"array\":[{\"Property1\":\"hello\",\"Property2\":\"world\"},{\"Property1\":\"hello2\",\"Property2\":\"world2\"}]}");
			Assert.IsNotNull( ao );
			Assert.IsNotNull( ao.array );
			Assert.AreEqual( 2, ao.array.Count );
			Assert.AreEqual( "hello", ao.array[0].Property1 );
			Assert.AreEqual( "world2", ao.array[1].Property2 );
		}
		
		public class SimpleObject
		{
			public string Property1{ get; set; }
			public string Property2{ get; set; }
		}
		
		public class ArrayObject
		{
			public IList<SimpleObject> array{ get; set; }
		}
		
		[JsonObject]
		public class NestedObject
		{
			public string PropertyA{ get; set; }
			public SimpleObject nested{ get; set; }
		}
		
		public class ImpliedObject
		{
			[JsonConverter(typeof(ValueTypeConvertor<Implied>))]
			public Implied Property1{ get; set; }
			public string Property2{ get; set; }
		}
		
		public class ImpliedObject2
		{
			[JsonConverter(typeof(ValueTypeConvertor<FBText>))]
			public FBText Property1{ get; set; }
			public string Property2{ get; set; }
		}
		
		public class Implied
		{
			public Implied(){}
			
			public Implied( string v )
			{
				this.Value = v;
			}
			public string Value{ get; set; }
			public string Language{ get; set; }
			
			public static implicit operator Implied( string v )
			{
				return new Implied( v );
			}
		}
		
		#endregion
	}
}
